package com.derbysoft.ota.application.translator.rs;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.ota.application.translator.MetaDatas;
import com.derbysoft.ota.application.util.Calendars;
import com.derbysoft.ota.application.util.Elements;
import com.derbysoft.ota.application.util.ParagraphTypes;
import com.derbysoft.ota.interfaces.protocol._2009a.DateTimeSpanType;
import com.derbysoft.ota.interfaces.protocol._2009a.RateType;
import com.derbysoft.ota.interfaces.protocol._2009a.RateType.Rate;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStayType.RoomRates.RoomRate;
import com.derbysoft.ota.interfaces.protocol._2009a.TPAExtensionsType;
import com.derbysoft.remote.dswitch.hotel.constants.PaymentType;
import com.derbysoft.remote.dswitch.hotel.dto.AvailRoomStayDTO;
import com.derbysoft.remote.dswitch.hotel.dto.RateDTO;
import com.derbysoft.remote.dswitch.hotel.dto.RatePlanDTO;
import com.derbysoft.remote.dswitch.hotel.dto.RoomRateDTO;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.googlecode.functionalcollections.FunctionalIterables;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.math.BigInteger;
import java.util.List;
import java.util.Map.Entry;

public class AvailRoomRateTranslator implements Translator<Entry<AvailRoomStayDTO, DateTimeSpanType>, RoomRate> {

	private final Translator<RateDTO, Rate> rateTranslator;

	@Inject
	public AvailRoomRateTranslator(Translator<RateDTO, Rate> rateTranslator) {
		this.rateTranslator = rateTranslator;
	}

	public RoomRate translate(Entry<AvailRoomStayDTO, DateTimeSpanType> source) {
		return roomRate(source.getKey(), source.getValue());
	}

	private RoomRate roomRate(final AvailRoomStayDTO switchAvailRoomStay, DateTimeSpanType roomRateDateRange) {
		final RatePlanDTO ratePlan = switchAvailRoomStay.getRatePlan();
		RoomRate roomRate = new RoomRate();
		roomRate.setRoomTypeCode(switchAvailRoomStay.getRoomType().getCode());
		roomRate.setRatePlanCode(ratePlan.getCode());
		if (switchAvailRoomStay.getQuantity() != null) {
			roomRate.setNumberOfUnits(BigInteger.valueOf(switchAvailRoomStay.getQuantity()));
		}

		Preconditions.checkNotNull(roomRateDateRange, "Please provide date range of hotel avail request");
		roomRate.setEffectiveDate(Calendars.of(roomRateDateRange.getStart()));
		roomRate.setExpireDate(Calendars.of(roomRateDateRange.getEnd()));
		roomRate.setExpireDateExclusiveIndicator(Boolean.TRUE);

		RoomRateDTO switchRoomRate = switchAvailRoomStay.getRoomRate();
		List<RateDTO> switchRates = switchRoomRate.getRates();
		if (CollectionUtils.isNotEmpty(switchRates)) {
			roomRate.setRates(new RateType());
			roomRate.getRates().getRate().addAll(
					FunctionalIterables.make(switchRates).map(
							new Function<RateDTO, Rate>() {
								public Rate apply(RateDTO switchRate) {
									return rate(switchRate, ratePlan.getPaymentType());
								}
							}).toCollection()
			);
		}

		if (StringUtils.isNotBlank(switchRoomRate.getDescription())) {
			roomRate.getRoomRateDescription().add(ParagraphTypes.of(switchRoomRate.getDescription()));
		}

		return roomRate;
	}

	private Rate rate(RateDTO switchRate, PaymentType paymentType) {
		Rate rate = rateTranslator.translate(switchRate);
		rate.setTPAExtensions(new TPAExtensionsType());
		rate.getTPAExtensions().getAny().add(Elements.of(MetaDatas.PAYMENT_TYPE_EXTENSION_KEY, paymentType.name()));
		return rate;
	}

}
